package ie.dcu.spca.data.db;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ie.dcu.spca.data.BasicDataManager;
import ie.dcu.spca.data.ItemDataManager;
import ie.dcu.spca.data.ItemUserDataManager;
import ie.dcu.spca.model.bean.ItemsUsers;
import ie.dcu.spca.model.dao.ItemsusersDao;

public class DBItemUserDataManager implements ItemUserDataManager {

    private ItemsusersDao iuD = new ItemsusersDao();
    private ItemUserWeightMap weightMap;

    private ItemsusersDao iuDao() {
        return iuD;
    }

    public DBItemUserDataManager() {
        weightMap = new ItemUserWeightMap();
    }

    @Override
    public int getCount(int itemId, int userId) {
        if (itemId == ItemDataManager.NEW_ITEM_ID)
            if (userId == 4)
                return 0;
            else
                return 1;
        weightMap.reload(iuDao());
        // int count = 0;
        // List<ItemsUsers> iuList =
        // iuDao().selectItemusersListByItemid(itemId);
        // for (ItemsUsers iu : iuList) {
        // count += getCountByUserId(iu, userId);
        // }
        // return count;
        return weightMap.get(itemId, userId);
    }

    static int getCountByUserId(ItemsUsers iu, int id) {
        int totCount = 0;
        id = id - 1;
        String users = iu.getUser_id();
        if (users.length() > id) {
            if (users.charAt(id) == (HAVE_TAG)) {
                totCount = iu.getCount();
            }
        }
        return totCount;
    }

    @Override
    public void updateOrCreate(int itemId,
            List<Map<String, Integer>> userIdWeightList) {
        List<ItemsUsers> iuList = iuDao().selectItemusersListByItemid(itemId);
        for (ItemsUsers iu : iuList)
            deleteItemUser(iu);
        int maxId = 0;
        int minWeight = 0;
        updateWeightMap(userIdWeightList, minWeight);
        do {
            maxId = getMaxId(userIdWeightList);
            minWeight = getMinWeight(userIdWeightList);
            insertIU(itemId, maxId, minWeight, userIdWeightList);
            updateWeightMap(userIdWeightList, minWeight);
        } while (userIdWeightList.size() > 0);
    }

    private void deleteItemUser(ItemsUsers iu) {
        weightMap.clear(iu.getItem_id());
        iuDao().deleteByBean(iu);
    }

    private void insertIU(int itemId, int maxId, int minWeight,
            List<Map<String, Integer>> userIdWeightList) {
        char[] users = new char[maxId];
        for (int i = 0; i < users.length; i++)
            users[i] = DONOT_HAVE_TAG;
        for (Map<String, Integer> m : userIdWeightList) {
            int userId = m.get(BasicDataManager.ID);
            users[userId - 1] = HAVE_TAG;
            weightMap.insert(itemId, userId, minWeight);
        }
        iuDao().insertItemsusers(itemId, new String(users), minWeight);
    }

    private void updateWeightMap(List<Map<String, Integer>> userIdWeightList,
            int weight) {
        int i = userIdWeightList.size();
        while (--i >= 0) {
            Map<String, Integer> m = userIdWeightList.get(i);
            int newWeight = m.get(BasicDataManager.WEIGHT) - weight;
            if (newWeight <= 0)
                userIdWeightList.remove(i);
            else
                m.put(BasicDataManager.WEIGHT, newWeight);
        }
    }

    private int getMaxId(List<Map<String, Integer>> userIdWeightList) {
        int maxId = 0;
        for (Map<String, Integer> m : userIdWeightList)
            maxId = Math.max(maxId, m.get(BasicDataManager.ID));
        return maxId;
    }

    private int getMinWeight(List<Map<String, Integer>> userIdWeightList) {
        int minWeight = Integer.MAX_VALUE;
        for (Map<String, Integer> m : userIdWeightList)
            minWeight = Math.min(minWeight, m.get(BasicDataManager.WEIGHT));
        return minWeight;
    }

}

class ItemUserWeightMap {
    private Map<Integer, Map<Integer, Integer>> dataMap;
    private boolean isReload;

    public ItemUserWeightMap() {
        dataMap = new HashMap<Integer, Map<Integer, Integer>>();
        isReload = false;
    }

    public void reload(ItemsusersDao dao) {
        if (isReload)
            return;
        isReload = true;
        List<ItemsUsers> iuList = (List) dao.selectAllBean();
        for (ItemsUsers iu : iuList) {
            for (int userId = 1; userId <= iu.getUser_id().length(); userId++)
                insert(iu.getItem_id(), userId, DBItemUserDataManager
                        .getCountByUserId(iu, userId));
        }
    }

    public void insert(int itemId, int userId, int count) {
        Map<Integer, Integer> weightMap = dataMap.get(itemId);
        if (weightMap == null) {
            weightMap = new HashMap<Integer, Integer>();
            dataMap.put(itemId, weightMap);
        }
        Integer nowW = weightMap.get(userId);
        if (nowW == null)
            nowW = 0;
        nowW += count;
        weightMap.put(userId, nowW);
    }

    public int get(int itemId, int userId) {
        Map<Integer, Integer> weightMap = dataMap.get(itemId);
        int count = 0;
        if (weightMap != null) {
            Integer w = weightMap.get(userId);
            if (w != null)
                count = w;
        }
        return count;
    }

    public void clear(int itemId) {
        dataMap.remove(itemId);
    }

}
